#include <iostream>
#include <memory>
#include <vector>
#include <string>
#include <string>
#include <fstream>
#include <streambuf>
#include <sstream>
#include <cstdlib>
#include <new>
#include <typeinfo>
#include <list>
#include <thread> // std::thread
#include <mutex>  // std::mutex

using namespace std;

// 参考: https://blog.csdn.net/misayaaaaa/article/details/53786215
// 参考: https://github.com/applenob/Cpp_Primer_Practice
// chapter 6



// 1. 实参和形参的区别的什么？
对于实参和形参的区别，可以简单的理解为：

形参：函数定义的时的参数—也就是无赋值的变量（作用是说明参数的类型）

实参：调用函数时使用的参数—也就是有赋值的变量（函数实际操作的对象）





// 6. 说明形参、局部变量以及局部静态变量的区别。编写一个函数，同时达到这三种形式
知识点1：局部变量：形参和函数体内部定义的变量统称为局部变量（注意其作用域）

知识点2：局部静态对象：知道程序的结束才被销毁的对象，不受块的约束
// 形参定义在函数形参列表里面；局部变量定义在代码块里面； 局部静态变量在程序的执行路径第一次经过对象定义语句时初始化，并且直到程序终止时才被销毁



#include <iostream>
#include <string>
#include <vector>
using namespace std;
 
int fact()//函数的声明及定义，不接受参数（如果接受参数，那么就为形参）
{
	static int My_number = 0;//局部静态变量
	My_number++;
	return My_number;
}
void main()
{	
	for (int i = 0;i<=10;i++)//i变量就是一个局部变量，只在for语句块中存在
	{
		cout<<fact()<<endl;
	}
	cout<<fact()<<endl;//查看其输出结果，即可明白局部静态变量的用法




// 13.
假设T是某种类型的名字，说明以下两个函数声明的区别： 一个是void f(T), 另一个是void f(&T)。

解：

void f(T)的参数通过值传递，在函数中T是实参的副本，改变T不会影响到原来的实参。 void f(&T)的参数通过引用传递，在函数中的T是实参的引用，T的改变也就是实参的改变
// 前者以传值方式传入参数，不能修改实参。后者以传址的方式传入参数，可以修改实参



// 20. 引用形参什么时候应该是常量引用？如果形参应该是常量引用，而我们将其设为了普通引用，会发生什么情况？
应该尽量将引用形参设为常量引用，除非有明确的目的是为了改变这个引用变量。 如果形参应该是常量引用，而我们将其设为了普通引用，那么常量实参将无法作用于普通引用形参




// 31.  什么情况下返回的引用无效？什么情况下返回常量的引用无效？
知识点1：返回的引用无效：局部临时变量或者局部对象的引用对于返回都是无效的，因为在函数终止之后，局部变量或者对象的引用不再指向有效的内存区域。若是常量在函数调用之前存在，引用即可用。

知识点2：可以对返回值是非常量引用的函数结果赋值。

// 当返回的引用的对象是局部变量时，返回的引用无效；当我们希望返回的对象被修改时，返回常量的引用无效
举个例子：

#include <iostream>
#include<string>
using namespace std;
 
char &Get_val(string &a, int ix)//函数的声明及定义，接受两个参数，返回类型为非常量引用
{
	return a[ix];//字符串某一位置的字母
}
int main(int argc, char *argv[])
{	
	string s = "an apple ";
	cout<<"字符串修改前为："<<s<<endl;
	Get_val(s,0) = 'A';//可以对非常量的引用返回值赋值
	cout<<"字符串修改后为："<<s<<endl;	
	return 0;//代表执行成功
}



// 39. 说明在下面的每组声明中第二条语句是何含义。 如果有非法的声明，请指出来。

(a) int calc(int, int);
	int calc(const int, const int);
(b) int get();
	double get();
(c) int *reset(int *);
	double *reset(double *);
解：

(a) 非法。因为顶层const不影响传入函数的对象，所以第二个声明无法与第一个声明区分开来。
(b) 非法。对于重载的函数来说，它们应该只有形参的数量和形参的类型不同。返回值与重载无关。
(c) 合法。




// 40. 下面的哪个声明是错误的？为什么？

(a) int ff(int a, int b = 0, int c = 0);
(b) char *init(int ht = 24, int wd, char bckgrnd);	
解：

(a) 正确。 (b) 错误。因为一旦某个形参被赋予了默认值，那么它之后的形参都必须要有默认值



int main()
{
   
    printf("hello c++ \n");
}